﻿using Basic.FlowApplication.AuditLocalEvent;
using Basic.FlowApplication.Interface;
using Basic.FlowApplication.Model;
using Basic.FlowCollect;
using Basic.FlowModel;
using Basic.FlowModel.AppItem;
using Basic.FlowModel.AuditLog;
using Basic.FlowRemoteModel;
using Basic.FlowRemoteModel.Application.Model;
using WeDonekRpc.Helper;
using WeDonekRpc.SqlSugar;

namespace Basic.FlowApplication.Extend
{
    internal class AppAuditCreateService : IAppAuditCreateService
    {
        private readonly IFlowAppItemCollect _AppItem;
        private readonly IFlowAppService _App;
        private readonly IFlowAuditLogCollect _AuditLog;
        private readonly IFlowNodeService _Flow;
        private readonly ITransactionService _Tran;

        public AppAuditCreateService ( IFlowAppItemCollect appItem,
            IFlowAppService app,
            IFlowAuditLogCollect auditLog,
            IFlowNodeService flow,
            ITransactionService tran )
        {
            this._AppItem = appItem;
            this._App = app;
            this._AuditLog = auditLog;
            this._Flow = flow;
            this._Tran = tran;
        }
        private AuditFlowBody _GetFlow ( FlowAppBody app, string ver )
        {
            if ( ver.IsNull() || ver == app.FlowVer )
            {
                return this._Flow.Get(app.FlowId.Value);
            }
            return this._Flow.Get(app.FlowId.Value, ver);
        }
        public CreateAuditResult CreateFlow ( CreateAuditArg arg, FlowUser user )
        {
            FlowAppBody app = this._App.Get(arg.AppId);
            if ( app.AppType == FlowAppType.外部应用 )
            {
                throw new ErrorException("flow.app.type.error");
            }
            else if ( app.Status != FlowAppStatus.启用 )
            {
                throw new ErrorException("flow.app.status.error");
            }
            AuditFlowBody flow = this._GetFlow(app, arg.Ver);
            AppItemAdd add = new AppItemAdd
            {
                AppId = arg.AppId,
                AppTitle = arg.DocTitle,
                AppClassify = app.AppClassify,
                CreateBy = user.EmpId,
                FlowId = flow.Id
            };
            FlowNode node = flow.Nodes[flow.BeginNode];
            AuditLogAdd logAdd = new AuditLogAdd
            {
                DocTitle = arg.DocTitle,
                AppType = app.AppType,
                CreateByDeptId = user.DeptId,
                CompanyId = user.CompanyId,
                BeginNodeId = flow.BeginNode,
                AppId = app.Id,
                FormId = node.FormId.GetValueOrDefault(flow.DefFormId.Value),
                CreateBy = user.EmpId,
                CreateByUnitId = user.UnitId,
                FlowId = app.FlowId.Value,
                LinkType = ConstDic.AppItemLinkType,
                NodeId = flow.Nodes.Select(a => new KeyValuePair<long, long>(a.Key, a.Value.RootNodeId)).ToArray(),
            };
            long logId;
            long itemId;
            using ( ILocalTransaction tran = this._Tran.ApplyTran() )
            {
                logAdd.LinkPk = this._AppItem.Add(add);
                logId = this._AuditLog.Add(logAdd, out itemId);
                tran.Commit();
            }
            new AuditBeginEvent
            {
                Body = new AuditBeginBody
                {
                    DocTitle = arg.DocTitle,
                    Flow = flow,
                    App = app,
                    LinkPk = logAdd.LinkPk,
                    LinkType = logAdd.LinkType,
                    LogId = logId,
                    ItemId = itemId,
                    User = user
                }
            }.AsyncSend();
            return new CreateAuditResult
            {
                ItemId = itemId,
                LogId = logId,
                IsNext = false
            };
        }
    }
}
